#include "const/oPreDefine.h"
#include "platform/oUnit.h"
#include "platform/oData.h"
using namespace platform;
#include "physics/oGroup.h"
//Group [1,2,3,4,5,6,7,8,9,10,11,12] for player
//Group [13] for player sensor
//Group [14] for terrain
//Group [15] for sense all
#define P1 1
#define P12 12
#define PSensor 13
#define Terrain 14
#define SenseAll 15

oData::oData()
{
	for (int p = P1;p <= P12;p++)
	{
		oGroup::setShouldContact(PSensor, p, true);
		oGroup::setShouldContact(Terrain, p, true);
		oGroup::setShouldContact(SenseAll, p, true);
	}
	oGroup::setShouldContact(SenseAll, Terrain, true);
}

void oData::setRelation( uint32 groupIndexA, uint32 groupIndexB, oRelation relation )
{
	uint32 key = groupIndexA<<16 | groupIndexB;
	_relationMap[key] = relation;
	key = groupIndexB | groupIndexA<<16;
	_relationMap[key] = relation;
}

void oData::setRelation( oGroup* groupA, oGroup* groupB, oRelation relation )
{
	oData::setRelation(groupA->getGroupIndex(), groupB->getGroupIndex(), relation);
}

oRelation oData::getRelation( oGroup* groupA, oGroup* groupB ) const
{
	uint32 key = groupA->getGroupIndex()<<16 | groupB->getGroupIndex();
	unordered_map<uint32, oRelation>::const_iterator it = _relationMap.find(key);
	return it != _relationMap.end() ? it->second : e_unkown;
}

oRelation oData::getRelation( oUnit* unitA, oUnit* unitB ) const
{
	return oData::getRelation(unitA->getGroup(), unitB->getGroup());
}

oGroup* oData::getSensePlayerGroup() const
{
	return oGroup::get(PSensor);
}

oGroup* oData::getTerrainGroup() const
{
	return oGroup::get(Terrain);
}

oGroup* oData::getSenseAllGroup() const
{
	return oGroup::get(SenseAll);
}

oData& oData::sharedData()
{
	static oData g_data;
	return g_data;
}

void oData::setDamageFactor( oDamageType damageType, oDefenceType defenceType, float bounus )
{
	uint32 key = damageType | defenceType;
	_damageBounusMap[key] = bounus;
}

float oData::getDamageFactor( oDamageType damageType, oDefenceType defenceType ) const
{
	uint32 key = damageType | defenceType;
	unordered_map<uint32, float>::const_iterator it = _damageBounusMap.find(key);
	if (it != _damageBounusMap.end())
	{
		return it->second;
	}
	return 0.0f;
}

bool oData::isPlayerUnit( oBody* body )
{
	int16 index = body->getGroup()->getGroupIndex();
	return P1 <= index && index <= P12;
}

bool oData::isTerrain( oBody* body )
{
	return body->getGroup() == oData::getTerrainGroup();
}
